<template>
  <div class="wrapper">
    <el-form :ref="formName" :model="innerformData" label-width="100px">
      <el-row>
        <el-col
          v-for="(item, index) in dynamicValidateForm"
          :key="index"
          :span="item.span||12"
          :style="item.type|rowHeight"
        >
          <el-form-item
            :label="item.label"
            :prop="item.name"
            :rules="{
              required: !read&&item.required, message: item.label+'不能为空', trigger: 'blur'
            }"
          >
            <template v-if="item.type === 'option'">
              <el-select v-model="innerformData[item.name]" style="width:100%" placeholder="请选择" :disabled="read">
                <el-option
                  v-for="i in filterOption(item)"
                  :key="i.value"
                  :label="i.label"
                  :value="i.value"
                />
              </el-select>
            </template>
            <el-input
              v-if="showInput(item.type)"
              v-model="innerformData[item.name]"
              :disabled="onlyRead"
              :readonly="read"
              clearable
              :type="item.type&&item.type.replace(/\s.*/, '')"
              :placeholder="item.placeholder"
              @focus="bindClick(item)"
            >
              <i v-if="item.config&&item.config.icon" slot="prefix" :class="['el-input__icon', innerformData[item.name]]" />
            </el-input>
            <el-switch
              v-if="showSwitch(item.type)"
              v-model="innerformData[item.name]"
              :disabled="onlyRead"
              :active-text="configParam(item).activeText||''"
              :inactive-text="configParam(item).inactiveText||''"
              :active-value="configParam(item).activeValue||true"
              :inactive-value="configParam(item).inactiveValue||false"
            />
            <template v-if="item.type=='select'">
              <el-popover
                placement="bottom"
                trigger="click"
                :width="fromLabelWidth(item)"
                popper-class="fromPopover"
              >
                <el-tree
                  ref="tree"
                  :data="filterOption(item)"
                  :props="item.config&&item.config.props||{}"
                  show-checkbox
                  node-key="id"
                  @check="handleCheckChange($event, item)"
                />
                <el-input
                  slot="reference"
                  :ref="`table${item.name}`"
                  v-model="treeValue"
                  v-popover:popover
                  clearable
                />
              </el-popover>
            </template>
            <template v-if="item.type === 'upload'">
              <el-upload
                class="avatar-uploader"
                :action="item.config.action"
                :show-file-list="false"
                :on-success="item.config.handleAvatarSuccess"
                :before-upload="item.config.beforeAvatarUpload"
              >
                <img v-if="innerformData[item.name]" :src="innerformData[item.name]" class="avatar">
                <i v-else class="el-icon-plus avatar-uploader-icon" />
              </el-upload>
            </template>
            <template v-if="item.type=='datePicker'">
              <el-date-picker
                v-model="innerformData[item.name]"
                type="date"
                style="width:100%;"
                placeholder="选择日期"
              />
            </template>
            <template v-if="item.type==='cascader'">
              <el-cascader
                v-model="innerformData[item.name]"
                style="width:100%;"
                :options="item.config&&item.config.options||[]"
                :show-all-levels="false"
                :disabled="read"
                :props="item.config&&item.config.props||{}"
                clearable
              />
            </template>
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item v-if="!read">
        <el-button type="primary" @click="submitForm">提交</el-button>
        <el-button @click="resetForm">取消</el-button>
      </el-form-item>
      <!-- 只读模式按钮样式 -->
      <el-form-item v-if="read">
        <el-button @click="resetForm">关闭</el-button>
      </el-form-item>
    </el-form>
    <el-dialog title="图标" :visible.sync="dialogVisible" destroy-on-close append-to-body width="80%">
      <div
        :style="{
          height: '50vh',
          overflow: 'auto'
        }"
      >
        <Icons @click="selectIcon" />
      </div>
    </el-dialog>
  </div>
</template>

<script>
import Icons from '@/views/icons/icons'
export default {
  name: 'JForm',
  components: { Icons },
  filters: {
    rowHeight(type) {
      const reg = ['upload']
      const result = reg.includes(type)
      if (result) return {}
      return {
        height: '46px'
      }
    }
  },
  props: {
    formConfig: {
      type: Array,
      default: () => ([])
    },
    onlyRead: {
      type: Boolean,
      default: false
    },
    read: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      dialogVisible: false,
      formName: 'dynamicValidateForm',
      innerformData: {},
      treeValue: '',
      currentItem: {}
    }
  },
  computed: {
    dynamicValidateForm: {
      get() {
        const data = this.formConfig
        const result = []
        data.forEach(item => {
          result.push(item)
        })
        return result
      }
    }
  },
  watch: {
    formConfig: {
      handler: function(newVal, oldVal) {
        if (newVal) {
          newVal.forEach(item => {
            const { value = null, name } = item
            if (value !== null) {
              this.innerformData = { ...this.innerformData, [name]: value }
            }
          })
        }
      },
      immediate: true
    }
  },
  created() {},
  mounted() {
  },
  methods: {
    fromLabelWidth(item) {
      const { name } = item
      let result = this.$refs[`table${name}`]
      let width = 0
      if (result) {
        if (Array.isArray(result)) result = result[0]
        width = result.$el.clientWidth || result.clientWidth
      }
      return width
    },
    /**
     * @description: 转换config中的参数
     * @param {*} item
     * @return {*}
     */
    configParam(item) {
      const { config = {}} = item
      return { ...config }
    },
    filterOption(item) {
      const { options = [] } = item.config || {}
      // if (item.type === 'select') { console.log(item.type, item.name, options) }
      return options
    },
    /**
     * @description: 根据传入的 type 来判断是否显示input
     * @param {String}
     * @return {type}
     */
    showInput(type = 'string') {
      const result = type.replace(/\s.*/, '')
      const types = ['string', 'date', 'email', 'number', 'password']
      return types.includes(result)
    },
    /**
     * @description: 是否显示 switch
     * @param {type}
     * @return {type}
     */
    showSwitch(type = 'string') {
      const result = type.replace(/\s.*/, '')
      const types = ['switch']
      return types.includes(result)
    },
    submitForm() {
      this.$refs[this.formName].validate(async(valid) => {
        if (valid) {
          this.$emit('handleBoxEvent', this.trimData(this.innerformData))
        } else {
          return false
        }
      })
    },
    trimData(formData) {
      const target = formData
      const result = {}
      this[this.formName].forEach(item => {
        const { name } = item
        target[name] !== undefined && (result[name] = target[name])
      })
      return result
    },
    resetForm() {
      this.$refs[this.formName].resetFields()
      this.$emit('handleBoxEvent')
    },
    bindClick(item) {
      if (this.read) return
      this.currentItem = item
      const { config: { icon = false } = {}} = item
      if (icon) {
        this.dialogVisible = true
      }
      this.$emit('itemClick', item)
    },
    handleCheckChange(obj, node) {
      console.log(obj, node)
      const { checkedKeys, checkedNodes } = node

      this.treeValue = checkedKeys.toString()
      this.treeValue = checkedNodes.map(i => i.title).toString()
    },
    selectIcon(icon) {
      const { name } = this.currentItem
      this.innerformData[name] = icon
      this.currentItem = {}
      this.dialogVisible = false
    }
  }
}
</script>

<style>
  .avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }
  .avatar-uploader .el-upload:hover {
    border-color: #409EFF;
  }
  .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
  }
  .avatar {
    width: 178px;
    height: 178px;
    display: block;
  }
  .fromPopover{
     box-sizing: border-box;
   }
</style>

<style lang="scss" scoped>
.wrapper{
   padding: 0px;
   margin: 0px;
}
</style>
